// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#include "Application.h"

namespace lagniappe
{

Application::Application()
{
}

Application::~Application()
{
}

void
Application::setup(System * sys)
{
	this->buildOperators(sys);
	this->connectGraph();
	sys->createResources();
	sys->setAppReference(this);
	activateMonitor(sys);
	//this->schedule(sys);
	return;
}

void
Application::setupProfiler(System * sys)
{
	this->buildOperators(sys, true);
	return;
}

void
Application::startLoop(System * sys)
{
	reader::Reader appReader;
	while(true) {
		std::string lineRead;
		lineRead = appReader.getLine();

		if(lineRead.find(commands::CMD_QUIT,0) == 0) {
			break;
		}
		if(lineRead.find(commands::CMD_REPORT,0) == 0) {
			sys->reportChannelUsage();
		}
		if(lineRead.find(commands::CMD_CONNECT,0) == 0) {
			SerialMonitorRequest * mr = new SerialMonitorRequest;
			mr->msgType = SET_SLAVE;
			std::string procname = sys->getMonProc()->getName() + "Ghost";
			strcpy(mr->reqBody.setSlave.procName, procname.c_str());
			RCon * rcon = new RCon(mon, static_cast<RData *>(mr), "", sizeof(*mr));
			sys->setMaster(rcon);			
			this->schedule(sys);	
		}
	}
	
}

void
Application::activateMonitor(System * sys)
{
	mon = new Monitor(sys);
	//lagniappe::ProcElement * tempProc = sys->getFreeProc(mon, lagniappe::INITIAL);
	ProcElement * tempProc = sys->getMonProc();
	std::cerr << "MonProc: " << tempProc->getName() << std::endl;
    //if(tempProc == NULL) tempProc = sys->roundRobin();
    sys->assignProc(tempProc, mon);
    assert(tempProc != NULL);
	mon->schedule(tempProc);
	for(std::map<std::string, CoreOp *>::iterator iter = opMap.begin(); iter != opMap.end(); iter++) {
		Operator * oper = dynamic_cast<Operator *>(iter->second);
		if(oper != NULL) {
			assert(mon != NULL);
			oper->setDestination(MONITOR_OUT_PORT, new std::pair<CoreOp *, std::string>(mon, ""));
		}
		
	}
}

}
